/*
 * @Description: 动态表单服务层
 */
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectModel } from 'nest-typegoose';
import { ReturnModelType } from '@typegoose/typegoose';
import { FormTemplate, FormField } from '../../libs/db/src/models/form-template.model';
import { FormSubmission, SubmissionData } from '../../libs/db/src/models/form-submission.model';
import { CreateFormTemplateDto } from './dto/create-form-template.dto';
import { UpdateFormTemplateDto } from './dto/update-form-template.dto';
import { AddFormFieldDto } from './dto/add-form-field.dto';
import { SubmitFormDto } from './dto/submit-form.dto';
import { QueryFormTemplateDto, QueryFormSubmissionDto } from './dto/query-form.dto';

@Injectable()
export class DynamicFormService {
  constructor(
    @InjectModel(FormTemplate)
    private readonly formTemplateModel: ReturnModelType<typeof FormTemplate>,
    @InjectModel(FormSubmission)
    private readonly formSubmissionModel: ReturnModelType<typeof FormSubmission>,
  ) { }

  /**
   * 创建表单模板
   * @param createFormTemplateDto 创建表单模板的数据传输对象
   * @returns 创建的表单模板
   */
  async createFormTemplate(createFormTemplateDto: CreateFormTemplateDto): Promise<FormTemplate> {
    try {
      // 生成唯一的表单标识符
      if (!createFormTemplateDto.formKey) {
        createFormTemplateDto.formKey = `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      }

      // 检查表单标识符是否已存在
      const existingForm = await this.formTemplateModel.findOne({ formKey: createFormTemplateDto.formKey });
      if (existingForm) {
        throw new BadRequestException('表单标识符已存在');
      }

      const formTemplate = new this.formTemplateModel(createFormTemplateDto);
      return await formTemplate.save();
    } catch (error) {
      if (error instanceof BadRequestException) {
        throw error;
      }
      throw new BadRequestException('创建表单模板失败');
    }
  }

  /**
   * 获取表单模板列表（分页）
   * @param queryDto 查询参数
   * @returns 表单模板列表和总数
   */
  async getFormTemplates(queryDto: QueryFormTemplateDto) {
    const { page = 1, limit = 10, formTemplateId, createdBy, isActive } = queryDto;
    const skip = (page - 1) * limit;

    // 构建查询条件
    const query: any = {};
    if (formTemplateId) {
      query.formTemplateId = formTemplateId;
    }
    if (createdBy) {
      query.createdBy = createdBy;
    }
    if (isActive !== undefined) {
      query.isActive = isActive;
    }

    const [templates, total] = await Promise.all([
      this.formTemplateModel.find(query).skip(skip).limit(limit).sort({ createdAt: -1 }),
      this.formTemplateModel.countDocuments(query),
    ]);

    return {
      data: templates,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 根据ID获取表单模板
   * @param id 表单模板ID
   * @returns 表单模板
   */
  async getFormTemplateById(id: string): Promise<FormTemplate> {
    const template = await this.formTemplateModel.findById(id);
    if (!template) {
      throw new NotFoundException('表单模板不存在');
    }
    return template;
  }

  /**
   * 根据表单标识符获取表单模板
   * @param formKey 表单标识符
   * @returns 表单模板
   */
  async getFormTemplateByKey(formKey: string): Promise<FormTemplate> {
    const template = await this.formTemplateModel.findOne({ formKey, isActive: true });
    if (!template) {
      throw new NotFoundException('表单模板不存在或已禁用');
    }
    return template;
  }

  /**
   * 更新表单模板
   * @param id 表单模板ID
   * @param updateFormTemplateDto 更新数据
   * @returns 更新后的表单模板
   */
  async updateFormTemplate(id: string, updateFormTemplateDto: UpdateFormTemplateDto): Promise<FormTemplate> {
    const template = await this.formTemplateModel.findByIdAndUpdate(
      id,
      updateFormTemplateDto,
      { new: true }
    );
    if (!template) {
      throw new NotFoundException('表单模板不存在');
    }
    return template;
  }

  /**
   * 删除表单模板
   * @param id 表单模板ID
   * @returns 删除结果
   */
  async deleteFormTemplate(id: string): Promise<{ message: string }> {
    const result = await this.formTemplateModel.findByIdAndDelete(id);
    if (!result) {
      throw new NotFoundException('表单模板不存在');
    }
    return { message: '表单模板删除成功' };
  }

  /**
   * 向表单模板添加字段
   * @param addFormFieldDto 添加字段的数据传输对象
   * @returns 更新后的表单模板
   */
  async addFormField(addFormFieldDto: AddFormFieldDto): Promise<FormTemplate> {
    const { formTemplateId, field } = addFormFieldDto;

    const template = await this.formTemplateModel.findById(formTemplateId);
    if (!template) {
      throw new NotFoundException('表单模板不存在');
    }

    // 检查字段名是否已存在
    const existingField = template.fields.find(f => f.fieldName === field.fieldName);
    if (existingField) {
      throw new BadRequestException('字段名已存在');
    }

    template.fields.push(field as FormField);
    return await template.save();
  }

  /**
   * 从表单模板移除字段
   * @param formTemplateId 表单模板ID
   * @param fieldName 字段名
   * @returns 更新后的表单模板
   */
  async removeFormField(formTemplateId: string, fieldName: string): Promise<FormTemplate> {
    const template = await this.formTemplateModel.findById(formTemplateId);
    if (!template) {
      throw new NotFoundException('表单模板不存在');
    }

    const fieldIndex = template.fields.findIndex(f => f.fieldName === fieldName);
    if (fieldIndex === -1) {
      throw new NotFoundException('字段不存在');
    }

    template.fields.splice(fieldIndex, 1);
    return await template.save();
  }

  /**
   * 提交表单数据
   * @param submitFormDto 提交表单的数据传输对象
   * @returns 提交记录
   */
  async submitForm(submitFormDto: SubmitFormDto): Promise<FormSubmission> {
    const { formTemplateId, formData, ...otherData } = submitFormDto;

    // 获取表单模板
    const template = await this.getFormTemplateById(formTemplateId);
    if (!template.isActive) {
      throw new BadRequestException('表单已禁用，无法提交');
    }

    // 验证表单数据
    await this.validateFormData(template, formData);

    // 构建结构化的提交数据
    const submissionData: SubmissionData[] = template.fields.map(field => ({
      fieldName: field.fieldName,
      fieldValue: formData[field.fieldName] || null,
      fieldLabel: field.fieldLabel,
      fieldType: field.fieldType,
    }));

    const submission = new this.formSubmissionModel({
      formTemplateId,
      formName: template.formName,
      formData,
      submissionData,
      ...otherData,
    });

    return await submission.save();
  }

  /**
   * 验证表单数据
   * @param template 表单模板
   * @param formData 表单数据
   */
  private async validateFormData(template: FormTemplate, formData: Record<string, any>): Promise<void> {
    const errors: string[] = [];

    for (const field of template.fields) {
      const value = formData[field.fieldName];

      // 检查必填字段
      if (field.required && (value === undefined || value === null || value === '')) {
        errors.push(`${field.fieldLabel}为必填字段`);
        continue;
      }

      // 如果有值，进行格式验证
      if (value !== undefined && value !== null && value !== '') {
        // 验证正则表达式
        if (field.validationRule) {
          const regex = new RegExp(field.validationRule);
          if (!regex.test(value.toString())) {
            errors.push(field.validationMessage || `${field.fieldLabel}格式不正确`);
          }
        }

        // 验证选项字段
        if (['select', 'radio'].includes(field.fieldType) && field.options) {
          if (!field.options.includes(value)) {
            errors.push(`${field.fieldLabel}的值不在可选范围内`);
          }
        }

        // 验证多选字段
        if (field.fieldType === 'checkbox' && field.options) {
          const values = Array.isArray(value) ? value : [value];
          for (const val of values) {
            if (!field.options.includes(val)) {
              errors.push(`${field.fieldLabel}的值不在可选范围内`);
            }
          }
        }
      }
    }

    if (errors.length > 0) {
      throw new BadRequestException(errors.join('; '));
    }
  }

  /**
   * 获取表单提交记录列表（分页）
   * @param queryDto 查询参数
   * @returns 提交记录列表和总数
   */
  async getFormSubmissions(queryDto: QueryFormSubmissionDto) {
    const { page = 1, limit = 10, formTemplateId, status, submitterId, startDate, endDate } = queryDto;
    const skip = (page - 1) * limit;

    // 构建查询条件
    const query: any = {};
    if (formTemplateId) {
      query.formTemplateId = formTemplateId;
    }
    if (status) {
      query.status = status;
    }
    if (submitterId) {
      query.submitterId = submitterId;
    }
    if (startDate || endDate) {
      query.createdAt = {};
      if (startDate) {
        query.createdAt.$gte = new Date(startDate);
      }
      if (endDate) {
        query.createdAt.$lte = new Date(endDate);
      }
    }

    const [submissions, total] = await Promise.all([
      this.formSubmissionModel.find(query)
        .populate('formTemplateId', 'formName formDescription')
        .skip(skip)
        .limit(limit)
        .sort({ createdAt: -1 }),
      this.formSubmissionModel.countDocuments(query),
    ]);

    return {
      data: submissions,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 根据ID获取表单提交记录
   * @param id 提交记录ID
   * @returns 提交记录
   */
  async getFormSubmissionById(id: string): Promise<FormSubmission> {
    const submission = await this.formSubmissionModel.findById(id)
      .populate('formTemplateId', 'formName formDescription fields');
    if (!submission) {
      throw new NotFoundException('提交记录不存在');
    }
    return submission;
  }

  /**
   * 更新提交记录状态
   * @param id 提交记录ID
   * @param status 新状态
   * @param processNote 处理备注
   * @param processedBy 处理者ID
   * @returns 更新后的提交记录
   */
  async updateSubmissionStatus(
    id: string,
    status: string,
    processNote?: string,
    processedBy?: string
  ): Promise<FormSubmission> {
    const submission = await this.formSubmissionModel.findByIdAndUpdate(
      id,
      {
        status,
        processNote,
        processedBy,
        processedAt: new Date(),
      },
      { new: true }
    );

    if (!submission) {
      throw new NotFoundException('提交记录不存在');
    }

    return submission;
  }
}